using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using PSE.Hosting.Management.Services.ServicesManager;
using System.Text.RegularExpressions;
using PSE.Hosting.Management.Common;
using PSE.Hosting.ServiceHoster.Logging;

namespace PSE.Hosting.Management.Windows
{
    public static class Business
    {
        private const char ServerConfigSeparator = '|';
        private const string Localhost = "localhost";
        private static Regex ServerNameRegEx = new Regex("^([^,~:|!@#$%\\^&'.\\(\\){}_]){1,24}$");
        private static Regex PackageNameRegEx = new Regex("^([^,~:|!@#$%\\^&'\\(\\){}]){1,24}$");
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        /// 

        #region Server Methods

        public static List<string> GetServersFromConfigurationFile()
        {
            List<string> servers = new List<string>();

            // Adiciona o localhost.
            servers.Add(Localhost);

            string serverList = Properties.Settings.Default.Servers;

            if (!string.IsNullOrEmpty(serverList))
            {
                string[] tempServers = serverList.Split(ServerConfigSeparator);
                for (int i = 0; i < tempServers.Length; i++)
                {
                    servers.Add(tempServers[i].ToUpper());
                }
            }

            return servers;
        }

        public static bool ValidateServerName(string serverName)
        {
            return ServerNameRegEx.IsMatch(serverName);
        }

        public static bool ValidatePackageName(string packageName)
        {
            return PackageNameRegEx.IsMatch(packageName);
        }

        public static void AddServer(string serverName)
        {
            // Read the added servers from configuration file.
            string serverList = Properties.Settings.Default.Servers;

            if (!String.IsNullOrEmpty(serverList))
                serverList += ServerConfigSeparator.ToString();

            serverList += serverName.ToUpper();

            Properties.Settings settings = Properties.Settings.Default;
            settings.Servers = serverList;
            settings.Save();
        }

        public static void RemoveServer(string serverName)
        {
            char[] separators = { ServerConfigSeparator };

            // Read the added servers from configuration file.
            string serverList = Properties.Settings.Default.Servers;

            serverList = serverList.Replace(serverName, "");
            serverList = serverList.Replace(ServerConfigSeparator.ToString() + ServerConfigSeparator.ToString(), ServerConfigSeparator.ToString());
            serverList = serverList.TrimStart(separators);
            serverList = serverList.TrimEnd(separators);

            Properties.Settings settings = Properties.Settings.Default;
            settings.Servers = serverList;
            settings.Save();

        }

        #endregion

        #region Package Methods

        public static List<PackageData> GetPackagesList(string serverName, bool error)
        {
            try
            {
                return ServiceFactory.Instance.GetService().GetPackageList(serverName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, error ? Logger.EntryType.Error : Logger.EntryType.Warning);
                throw;
            }
        }

        public static void AddPackage(string serverName, string packageName, string domain, string userName, string password)
        {
            try
            {
                ServiceFactory.Instance.GetService().AddPackage(serverName, packageName.ToUpper(), domain, userName, password);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void UpdatePackage(string serverName, string packageName, string domain, string userName, string password)
        {
            try
            {
                ServiceFactory.Instance.GetService().UpdatePackage(serverName, packageName.ToUpper(), domain, userName, password);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void RemovePackage(string serverName, string packageName)
        {
            try
            {
                ServiceFactory.Instance.GetService().RemovePackage(serverName, packageName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void StartPackage(string serverName, string packageName, bool startAssemblies)
        {
            try
            {
                ServiceFactory.Instance.GetService().StartPackage(serverName, packageName, startAssemblies);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void StopPackage(string serverName, string packageName)
        {
            try
            {
                ServiceFactory.Instance.GetService().StopPackage(serverName, packageName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void StopPackage(string serverName, string packageName, bool save)
        {
            try
            {
                ServiceFactory.Instance.GetService().StopPackage(serverName, packageName, save);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        #endregion

        #region Assembly Methods

        public static List<AssemblyData> GetAssemblyList(string serverName, string packageName)
        {
            try
            {
                return ServiceFactory.Instance.GetService().GetAssemblyList(serverName, packageName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void StartAssembly(string serverName, string packageName, string fileName)
        {
            try
            {
                ServiceFactory.Instance.GetService().StartAssembly(serverName, packageName, fileName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void AddAssembly(string serverName, string packageName, string fileName)
        {
            string assemblyFullName = String.Empty;

            try
            {
                ServiceFactory.Instance.GetService().AddAssembly(serverName, packageName, assemblyFullName, fileName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void RemoveAssembly(string serverName, string packageName, string assembly)
        {
            try
            {
                ServiceFactory.Instance.GetService().RemoveAssembly(serverName, packageName, assembly);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        #endregion

        #region Service Methods

        /// <summary>
        /// Get the list of the WCF services of the specified assembly.
        /// </summary>
        /// <param name="serverName"></param>
        /// <param name="packageName"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static List<ServiceData> GetServiceList(string serverName, string packageName, string fileName)
        {
            try
            {
                return ServiceFactory.Instance.GetService().GetServiceList(serverName, packageName, fileName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void StartService(string serverName, string packageName, string assembly, string serviceName)
        {
            try
            {
                ServiceFactory.Instance.GetService().StartService(serverName, packageName, assembly, serviceName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }


        public static void StopService(string serverName, string packageName, string assembly, string serviceName)
        {
            try
            {
                ServiceFactory.Instance.GetService().StopService(serverName, packageName, assembly, serviceName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void StartWindowsService(string serverName, bool asynchronous, bool startAll)
        {
            try
            {
                ServiceFactory.Instance.GetService().StartWindowsService(serverName, asynchronous, startAll);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }

        public static void StopWindowsService(string serverName)
        {
            try
            {
                ServiceFactory.Instance.GetService().StopWindowsService(serverName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex, Logger.EntryType.Error);
                throw;
            }
        }        

        #endregion
    }
}
